package Concurrency2.Chapter03_CAS_Atomic.P01_CASUsage;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用Unsafe实现无锁编程
 */
public class T02_AutoIncrement {
    private volatile long value = 0L;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException {
        T02_AutoIncrement autoIncrement = new T02_AutoIncrement();
        Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        long valueOffset = unsafe.objectFieldOffset(T02_AutoIncrement.class.getDeclaredField("value"));
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService pool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            pool.submit(() -> {
                for (int j = 0; j < 1000000; j++) {
                    autoIncrement.some(unsafe, valueOffset);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println("value:" + autoIncrement.value);
        pool.shutdownNow();
    }

    private void some(Unsafe unsafe, long valueOffset) {
        long oldValue = value;
        do {
            oldValue = value;
        } while (!unsafe.compareAndSwapLong(this, valueOffset, oldValue, oldValue + 1));
    }
}
